home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech's Sprocket™ / Sprocket (original from 1994) / Sprocket / Lib / SprocketMain.cp < prev    next >
Encoding:
Text File  |  1994-12-06  |  16.3 KB  |  643 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        SprocketMain.cp
  3.  
  4.     Contains:    The “guts” of a Macintosh application.
  5.  
  6.     Written by: Dave Falkenburg and many other SmartFriends™
  7.  
  8.     Copyright:    © 1993-94 by Dave Falkenburg, all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.      
  12.         <13>     12/6/94    DRF        kUnresolvedSymbolAddress isn’t a Ptr in the latest universal
  13.                                     interfaces.
  14.         <12>    11/23/94    DRF        InstallAppleEventHandlers is now called InitAppleEventRoutines.
  15.         <11>    11/16/94    DRF        Added an explicit #include <Traps.h> for latest universal
  16.                                     headers. Also killed off a CFront warning.
  17.         <10>    11/12/94    DRF        Revised QuickDrawGX initialization based on changes made by Jon
  18.                                     Summer. We now use a 'gasz' resource to setup the size of the
  19.                                     graphics heap. Also we are now always TSM aware, not just when
  20.                                     TSMTE is around.
  21.          <9>     11/8/94    DRF        Rolled in LDR’s TSM fixes. Add fonts to the Fonts menu if it
  22.                                     exists. Also, stop openning up the preferences file here.
  23.          <8>     9/27/94    DRF         AppLib.h is now Sprocket.h, also fixed scrap coercion routines
  24.                                      and eliminated HandleUpdate.
  25.          <7>      9/9/94    DRF        Reordered headers and removed redundant #includes.
  26.                                     Conditionalized AOCE support. Also made changes to
  27.                                     TSMEventWrapper to be more like the code in InlineInputSample.
  28.          <6>      9/8/94    DRF        Add HiliteMenu(0) calls after calls to menu handling code
  29.                                     because TSMMenuSelect doesn’t do it. Also reorganized some GX
  30.                                     stuff: allocate and release a graphicsclient (Cam claims this
  31.                                     works on his machine), and turn on all the graphics errors and
  32.                                     notices if qDebug is set.
  33.          <5>      9/7/94    DRF        Rearrange YieldToAnyThread calls to make quitting faster.
  34.          <4>      9/4/94    DRF        Rearrange local variables in HandleMouseDown.
  35.          <3>      9/1/94    DRF        Stop including "MailableWindow.h" here.
  36.          <2>      9/1/94    DRF        More fixes for inline input, but we’re not really done yet.
  37.  */
  38.  
  39. #include "Sprocket.h"
  40.  
  41. #include <limits.h>        //    For LONG_MAX
  42.  
  43. #include <Fonts.h>
  44. #include <Desk.h>
  45. #include <GestaltEqu.h>
  46. #include <DiskInit.h>
  47. #include <Threads.h>
  48. #include <FragLoad.h>    //    for kUnresolvedSymbolAddress
  49. #include <Traps.h>
  50.  
  51. #if    qInlineInputAware
  52. #include <TextServices.h>
  53. #include <TSMTE.h>
  54. #endif
  55.  
  56. #if    qUseQuickDrawGX
  57. #include <graphics macintosh.h>
  58. #include <graphics routines.h>
  59. #include <graphics libraries.h>
  60. #include <PrintingManager.h>
  61. #endif
  62.  
  63. #include "StandardMenus.h"
  64. #include "Window.h"
  65. #include "SplashWindow.h"
  66. #include "AppleEventHandling.h"
  67.  
  68.  
  69. //    Function Prototypes
  70.  
  71. void    main(void);
  72. void    MainEventLoop(void);
  73.  
  74. void    HandleMouseDown(TWindow * topWindowObj, EventRecord * anEvent);
  75. void    HandleClose(WindowPtr aWindow);
  76.  
  77.  
  78. //    Globals
  79.  
  80. Boolean                gDone = false;
  81. Boolean                gMenuBarNeedsUpdate = true;
  82.  
  83. Boolean                gHasColorQuickdraw = false;
  84. Boolean                gHasThreadManager = false;
  85. Boolean                gHasDragManager = false;
  86. Boolean                gHasAppleScript = false;
  87. Boolean                gHasDisplayManager = false;
  88.  
  89. GrafPtr                gWindowManagerPort;
  90. Rect                gDeskRectangle;
  91. RgnHandle            gMouseRegion = nil;
  92.  
  93. short                gPreferencesRsrcRefNum;
  94.  
  95. #if    qAOCEAware
  96. Boolean                gHasAOCE = false;
  97. #endif
  98.  
  99. #if    qInlineInputAware
  100. Boolean                gHasTextServices = false;
  101. Boolean                gHasTSMTE = false;
  102.  
  103. Boolean                TSMEventWrapperForKotoeri(EventRecord *anEvent);
  104.  
  105. #endif
  106.  
  107. #if    qUseQuickDrawGX
  108. Boolean                gHasQuickDrawGX = false;
  109. long                gQuickDrawGXVersion = 0;
  110. long                gQuickDrawGXPrintingVersion = 0;
  111. gxGraphicsClient    gQuickDrawGXClient;
  112. #endif
  113.  
  114.  
  115. //    Values that can be adjusted by other application code to change
  116. //    the behavior of the MainEventLoop.
  117. //
  118. //    Rules of thumb:
  119. //
  120. //        Increase gXXXRunQuantum (and decrease gXXXSleepQuantum) when:
  121. //            The application has many threads running that need time
  122. //
  123. //        Decrease gXXXRunQuantum when:
  124. //            Sending AppleEvents to other applications
  125. //            Launching other applications
  126. //            Running in the background
  127.  
  128. unsigned long    gForegroundRunQuantum = 0;
  129. unsigned long    gForegroundSleepQuantum = GetCaretTime();
  130. unsigned long    gBackgroundRunQuantum = 0;
  131. unsigned long    gBackgroundSleepQuantum = LONG_MAX;
  132.  
  133.  
  134. //    Globals used to “tune” the performance of MainEventLoop
  135. //    (assume we’ll be starting in the foreground)
  136.  
  137. static    unsigned long    gRunQuantum = gForegroundRunQuantum;
  138. static    unsigned long    gSleepQuantum = gForegroundSleepQuantum;
  139.  
  140. #ifdef    powerc
  141. #ifndef    __MWERKS__
  142. QDGlobals    qd;
  143. #endif
  144. #endif
  145.  
  146. void
  147. main(void)
  148.     {
  149.     long        feature;
  150.  
  151.     MaxApplZone();
  152.     MoreMasters();
  153.     MoreMasters();
  154.     MoreMasters();
  155.     MoreMasters();
  156.  
  157.     InitGraf(&qd.thePort);    
  158.     InitFonts();
  159.     InitWindows();
  160.     InitMenus();
  161.     TEInit();
  162.     InitDialogs(nil);
  163.  
  164.  
  165.     if (GetToolTrapAddress(_Unimplemented) == GetOSTrapAddress(_Gestalt))
  166.         FatalErrorAlert(kCoreErrorStrings,kUnsupportedSystemSoftware);
  167.  
  168.     if (Gestalt(gestaltQuickdrawFeatures,&feature) == noErr)
  169.         gHasColorQuickdraw = ((feature & (1 << gestaltHasColor)) != 0);
  170.  
  171.     
  172.     TSplashWindow * splashWindow = new TSplashWindow;
  173.  
  174.     //    Check for and Initialize QuickDraw GX early on to avoid heap fragmentation
  175.     
  176. #if    qUseQuickDrawGX
  177.     //    Check for and initialize QuickDrawGX
  178.     if (Gestalt(gestaltGXVersion, &gQuickDrawGXVersion) == noErr)
  179.         {
  180.         if (Gestalt(gestaltGXPrintingMgrVersion, &gQuickDrawGXPrintingVersion) == noErr)
  181.             {
  182. #ifdef    powerc
  183.             if ((Ptr) GXEnterGraphics != kUnresolvedSymbolAddress)
  184. #endif
  185.             gHasQuickDrawGX = true;
  186.             }
  187.         }
  188.  
  189.     if (gHasQuickDrawGX)
  190.         {
  191.         // Initialize the graphics and printing environments.
  192.         //    For additional details see "IM: QD GX Environment & Utilities."
  193.         
  194.         //    We let QuickDraw GX look for a resource  of type 'gasz' with an ID of 0.
  195.         //    GX uses the first long word of that resource as the graphics heap size.
  196.         //    To determine the memory requirements of your graphics client heap see:
  197.         //    “IM: QD GX Environment & Utilities pp2-8,2-9”
  198.         
  199.         //    NOTE:    If your application does not provide this resource,
  200.         //            QuickDraw GX version 1.0 uses a default size of 600 KB.
  201.  
  202.         gQuickDrawGXClient = GXNewGraphicsClient(nil, kUseGraphicsSizeResource, kAllowGXToExtendGraphicsHeap);
  203.         if (gQuickDrawGXClient)
  204.             {
  205.             //    NOTE:    GXNewGraphicsClient() does not allocate memory to the heap
  206.             //            until GXEnterGraphics()    is called, so go ahead and call it now
  207.             //            while we have a chance to deal with things nicely.
  208.             //
  209.             // NOTE:    GXEnterGraphics() should only fail if there is not enough memory. 
  210.             
  211.             GXEnterGraphics();
  212.  
  213.             if (GXGetGraphicsError(nil) == noErr)
  214.                 {
  215. #if    qUseQuickDrawGXDebugging
  216.                 // If qUseQuickDrawGXDebugging = TRUE, enable on GX Validation and graphics library errors & notices.
  217.  
  218.                 //    NOTES from Jon Summers:
  219.                 //    As you increase the amount of validation, drawing speed will SLOW
  220.                 //    down due to all of the internal checking. Also, if you play with
  221.                 //    settings enough validation seems to become inconsistent
  222.  
  223.                 GXSetValidation(    //    gxInternalValidation    |
  224.                                     //    gxAllObjectValidation    |
  225.                                     //    gxApHeapValidation        |
  226.                                         gxPublicValidation);        // check parameters to public routines
  227.  
  228.                 //    This functionality will only work with the "debugging" version of QuickDraw GX.
  229.                 //    If you don't have the debugging version installed, these functions will not work. 
  230.  
  231.                 SetGraphicsLibraryErrors();
  232.                 SetGraphicsLibraryNotices();    
  233. #endif
  234.                 if (GXInitPrinting() != noErr)        // See IM: QuickDraw GX Printing
  235.                     {
  236.                     //    We couldn’t initialize printing, so clean up pretend GX isn’t around
  237.                     //    ••• For safety’s sake, we’ll probably want to bail here.
  238.                     
  239.                     if (gQuickDrawGXClient)
  240.                         GXDisposeGraphicsClient(gQuickDrawGXClient);
  241.                     gHasQuickDrawGX = false;
  242.                     }
  243.                 }
  244.             }
  245.         }
  246.  
  247.     if (gQuickDrawGXClient)
  248.         InitCommonColors();        // Initialize the CommonColors Library.
  249. #if    qRequireQuickDrawGX
  250.     else
  251.         FatalErrorAlert(kCoreErrorStrings, kNeedsQuickdrawGX);
  252. #endif    //    qRequireQuickDrawGX
  253. #endif    //    qUseQuickDrawGX
  254.  
  255.  
  256.     if ((Gestalt(gestaltAppleEventsAttr,&feature) == noErr) &&
  257.         (feature & (1 << gestaltAppleEventsPresent)))
  258.         {
  259.         //    Figure out if we need to do AppleEvent recording
  260.         gHasAppleScript = ((feature & (1 << gestaltScriptingSupport)) != 0);
  261.         }
  262.     else
  263.         FatalErrorAlert(kCoreErrorStrings,kUnsupportedSystemSoftware);
  264.  
  265. #if    qInlineInputAware
  266.     if ((Gestalt(gestaltTSMgrVersion,&feature) == noErr) && (feature >= 1))
  267.         {
  268.         gHasTextServices = true;
  269.         if (Gestalt(gestaltTSMTEAttr, &feature) == noErr)
  270.             gHasTSMTE = (feature & (1 << gestaltTSMTEPresent));
  271.  
  272.         if (InitTSMAwareApplication() != noErr)
  273.             {
  274.             gHasTextServices = false;
  275.             gHasTSMTE = false;
  276.             }
  277.         }
  278.  
  279. #endif
  280.  
  281.     if (Gestalt(gestaltThreadMgrAttr,&feature) == noErr)
  282.         {
  283. #ifdef    powerc
  284.         //    If running on a PowerPC, make sure that we not only have the
  285.         //    68K Thread Manager, but also the PowerPC shared library, too.
  286.         //    Because of the wonders of weak linking and out of memory errors
  287.         //    we need to also check to make sure that an entrypoint in the library
  288.         //    is there, too. 
  289.         if ((Ptr) NewThread != (Ptr) kUnresolvedSymbolAddress)
  290.             gHasThreadManager = ((feature & ((1 << gestaltThreadMgrPresent) | (1 << gestaltThreadsLibraryPresent))) != 0);
  291. #else
  292.         gHasThreadManager = ((feature & (1 << gestaltThreadMgrPresent)) != 0);
  293. #endif
  294.         }
  295.  
  296. #if    qRequireThreadManager
  297.     if (gHasThreadManager == false)
  298.         FatalErrorAlert(kCoreErrorStrings, kNeedsThreadManager);
  299. #endif
  300.  
  301.     //    Check for and install Drag Manager callbacks
  302.     if (Gestalt(gestaltDragMgrAttr,&feature) == noErr)
  303.         {
  304. #ifdef    powerc
  305.         //    If running on a PowerPC, make sure that we not only have the
  306.         //    68K Drag Manager, but also the PowerPC shared library, too.
  307.         if ((Ptr) NewDrag != (Ptr) kUnresolvedSymbolAddress)
  308.             gHasDragManager = ((feature & ((1 << gestaltDragMgrPresent) | (1 << gestaltPPCDragLibPresent))) != 0);
  309. #else
  310.         gHasDragManager = ((feature & (1 << gestaltDragMgrPresent)) != 0);
  311. #endif
  312.  
  313.         if (gHasDragManager)
  314.             {
  315.             InstallTrackingHandler(NewDragTrackingHandlerProc(CallWindowDragTrackingHandler),(WindowPtr) nil,nil);
  316.             InstallReceiveHandler(NewDragReceiveHandlerProc(CallWindowDragReceiveHandler),(WindowPtr) nil,nil);
  317.             }
  318.         }
  319.  
  320.     //    Check for Display Manager
  321.     if (Gestalt(gestaltDisplayMgrAttr,&feature) == noErr)
  322.         gHasDisplayManager = ((feature & (1 << gestaltDisplayMgrPresent)) != 0);
  323.  
  324. #if    qAOCEAware    
  325.     //    Check for and initialize AOCE Standard Mail package if it exists
  326.     if ((Gestalt(gestaltSMPMailerVersion,&feature) == noErr) && (feature != 0))
  327.         {
  328. #ifdef    powerc
  329.         if ((Ptr) SMPInitMailer != kUnresolvedSymbolAddress)
  330.             gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
  331. #else
  332.         gHasAOCE = (SMPInitMailer(kSMPVersion) == noErr);
  333. #endif
  334.         }
  335. #endif
  336.  
  337.     //    Initialize our AppleEvent Handling Routines
  338.     InitAppleEventRoutines();
  339.  
  340.     //    Setup desktop rectangle for dragging windows around            
  341.     GetWMgrPort(&gWindowManagerPort);
  342.     gDeskRectangle = (**GetGrayRgn()).rgnBBox;
  343.  
  344.     //    Get the default menubar
  345.     SetMenuBar(GetNewMBar(rMenuBar));
  346.     AddResMenu(GetMHandle(mApple),'DRVR');
  347.  
  348.     // Add fonts to the font menu if it installed
  349.     if (GetMHandle(mFont))
  350.         AddResMenu(GetMHandle(mFont),'FONT');
  351.     
  352.     if (SetupApplication() == noErr)
  353.         {
  354.         delete    splashWindow;    //    get rid of the splash screen
  355.         MainEventLoop();
  356.         TearDownApplication();
  357.         }
  358.  
  359. #if    qInlineInputAware
  360.     if (gHasTextServices)
  361.         (void) CloseTSMAwareApplication();
  362. #endif
  363.         
  364. #if    qUseQuickDrawGX
  365.     //    Tear down QuickDrawGX
  366.     if (gHasQuickDrawGX && gQuickDrawGXClient)
  367.         {
  368.         DisposeCommonColors();
  369.         GXExitPrinting();        // Close the new printing mgr. 
  370.         GXExitGraphics();        // Deallocate all of the default structures
  371.         GXDisposeGraphicsClient(gQuickDrawGXClient);    
  372.         }
  373. #endif
  374.     }
  375.  
  376.  
  377. void
  378. MainEventLoop(void)
  379.     {
  380.     EventRecord        anEvent;
  381.     unsigned long    nextTimeToCheckForEvents = 0;
  382.     
  383.     while (!gDone)
  384.         {
  385.         if (gMenuBarNeedsUpdate)
  386.             {
  387.             gMenuBarNeedsUpdate = false;
  388.             DrawMenuBar();
  389.             }
  390.  
  391.         if (gHasThreadManager)
  392.             YieldToAnyThread();
  393.  
  394.         if ((gRunQuantum == 0) ||
  395.             (TickCount() > nextTimeToCheckForEvents))
  396.             {
  397.             nextTimeToCheckForEvents = TickCount() + gRunQuantum;
  398.             
  399.             (void) WaitNextEvent(everyEvent,&anEvent,gSleepQuantum,gMouseRegion);
  400.                         
  401. #if    qInlineInputAware
  402.             if (gHasTextServices && TSMEventWrapperForKotoeri(&anEvent))
  403.                 {
  404.                 }
  405.             else
  406. #endif
  407.                 HandleEvent(&anEvent);
  408.             }
  409.         }
  410.     }
  411.  
  412. #if    qInlineInputAware
  413.  
  414. Boolean
  415. TSMEventWrapperForKotoeri(EventRecord *anEvent)
  416.     {
  417.     short        oldFont;
  418.     ScriptCode    keyboardScript;
  419.     Boolean        didTSMHandleTheEvent = false;
  420.  
  421.     //    This snippet of code is from TE 27: Inline Input & TextEdit
  422.     //    and is related to working around a bug in Kotoeri, one of the
  423.     //    Japanese Input methods when operating in a mixed script
  424.     //    environment (e.g., Japanese Language Kit)
  425.     
  426.     // make sure we have a port and it's not the Window Manager port
  427.     if (qd.thePort != nil)
  428.         {
  429.         oldFont            = qd.thePort->txFont;
  430.         keyboardScript    = GetScriptManagerVariable(smKeyScript);
  431.  
  432.         if (FontToScript(oldFont) != keyboardScript)
  433.             TextFont(GetScriptVariable(keyboardScript, smScriptAppFond));
  434.         }
  435.  
  436.     didTSMHandleTheEvent = TSMEvent(anEvent);
  437.     
  438.     TextFont(oldFont);        //    restore the font, even though the sample code didn’t
  439.  
  440.     return didTSMHandleTheEvent;
  441.     }
  442.  
  443. #endif    
  444.  
  445.  
  446.  
  447. void
  448. HandleEvent(EventRecord *anEvent)
  449.     {
  450.     TWindow    * wobj;
  451.     
  452.     if (anEvent->what != updateEvt)
  453.         wobj = GetWindowObject(FrontNonFloatingWindow());
  454.     else
  455.         wobj = GetWindowObject((WindowPtr) anEvent->message);
  456.  
  457.     if (wobj != nil)
  458. #if    qInlineInputAware
  459.         // give text services a chance to set the cursor shape
  460.         if (gHasTextServices && SetTSMCursor(anEvent->where))
  461.             ;    // do nothing, TSM did it for me
  462.         else    
  463. #endif
  464.             wobj->AdjustCursor(anEvent);
  465.     
  466.     if ((wobj != nil) && wobj->EventFilter(anEvent))
  467.         return;
  468.         
  469.     else switch (anEvent->what)
  470.         {
  471.         case    nullEvent:
  472.             if (wobj != nil)
  473.                 wobj->Idle(anEvent);
  474.             break;
  475.             
  476.         case    mouseDown:
  477.             HandleMouseDown(wobj,anEvent);
  478.             break;
  479.         
  480.         case    keyDown:
  481.         case    autoKey:
  482.             if (anEvent->modifiers & cmdKey)
  483.                 {
  484.                 long    menuResult = MenuKey((short) anEvent->message & charCodeMask);
  485. #if    qInlineInputAware
  486.                 if (!(gHasTextServices && TSMMenuSelect(menuResult)))
  487. #endif
  488.                     HandleMenu(wobj,menuResult);
  489.                 HiliteMenu(0);
  490.                 }
  491.             else if (wobj != nil)
  492.                 wobj->KeyDown(anEvent);
  493.             break;
  494.             
  495.         case    updateEvt:
  496.             {
  497.             GrafPtr        oldPort;
  498.             WindowPtr    aWindow = (WindowPtr) anEvent->message;    
  499.                 
  500.             GetPort(&oldPort);
  501.             SetPort(aWindow);
  502.             BeginUpdate(aWindow);
  503.             if (wobj != nil)
  504.                 wobj->Draw();
  505.             EndUpdate(aWindow);
  506.             SetPort(oldPort);
  507.             }
  508.             break;
  509.             
  510.         case diskEvt:
  511.             if (anEvent->message >> 16)
  512.                 {
  513.                 static    Point    where = {50,50};
  514.                 (void) DIBadMount(where,anEvent->message);
  515.                 }
  516.             break;
  517.                 
  518.         case    osEvt:
  519.             switch ((anEvent->message & osEvtMessageMask) >> 24)
  520.                 {
  521.                 case    mouseMovedMessage:
  522.                     break;
  523.                     
  524.                 case    suspendResumeMessage:                    
  525.  
  526.                     SuspendResumeWindows((anEvent->message & resumeFlag) != 0);
  527.  
  528.                     if (anEvent->message & resumeFlag)
  529.                         {
  530.                         if (anEvent->message & convertClipboardFlag)
  531.                             ReadLocalClipboardFromScrap();
  532.  
  533.                         gRunQuantum = gForegroundRunQuantum;
  534.                         gSleepQuantum = gForegroundSleepQuantum;
  535.                         }
  536.                     else
  537.                         {
  538.                         if (anEvent->message & convertClipboardFlag)
  539.                             WriteLocalClipboardToScrap();
  540.                         gRunQuantum = gBackgroundRunQuantum;
  541.                         gSleepQuantum = gBackgroundSleepQuantum;
  542.                         }
  543.  
  544.                     break;
  545.                 }
  546.             break;
  547.         
  548.         case    kHighLevelEvent:
  549.             (void) AEProcessAppleEvent(anEvent);
  550.             break;
  551.             
  552.         default:
  553.             break;
  554.         }
  555.     }
  556.  
  557. void
  558. HandleMouseDown(TWindow * topWindowObj,EventRecord *anEvent)
  559.     {
  560.     WindowPtr    aWindow;
  561.     TWindow        *wobj;
  562.     short        partCode;
  563.  
  564.     partCode = FindWindow(anEvent->where,&aWindow);
  565.     wobj = GetWindowObject(aWindow);
  566.     switch(partCode)
  567.         {
  568.         case    inMenuBar:
  569.             long    menuResult = MenuSelect(anEvent->where);
  570. #if    qInlineInputAware
  571.             if (!(gHasTextServices && TSMMenuSelect(menuResult)))
  572. #endif
  573.                 HandleMenu(topWindowObj,menuResult);
  574.             HiliteMenu(0);
  575.             break;
  576.             
  577.         case    inSysWindow:
  578.             SystemClick(anEvent,aWindow);
  579.             break;
  580.             
  581.         case    inContent:
  582.             if (wobj)
  583.                 {
  584.                 GrafPtr    oldPort;
  585.                 
  586.                 GetPort(&oldPort);
  587.                 SetPort(aWindow);
  588.                 GlobalToLocal(&anEvent->where);
  589.                 wobj->Click(anEvent);
  590.                 SetPort(aWindow);
  591.                 }
  592.             break;
  593.             
  594.         case    inDrag:
  595.             if (wobj)
  596.                 wobj->Drag(anEvent->where);
  597.             break;
  598.             
  599.         case    inGrow:
  600.             if (wobj)
  601.                 wobj->Grow(anEvent->where);
  602.             break;
  603.             
  604.         case    inGoAway:
  605.             if (TrackGoAway(aWindow,anEvent->where))
  606.                 HandleClose(aWindow);
  607.             break;
  608.  
  609.         case    inZoomIn:
  610.         case    inZoomOut:
  611.             if (TrackBox(aWindow,anEvent->where,partCode) && (wobj))
  612.                 wobj->Zoom(partCode);
  613.             break;
  614.             
  615.         default:
  616.             break;
  617.         }
  618.     }
  619.     
  620.  
  621. void
  622. HandleClose(WindowPtr aWindow)
  623.     {
  624.     short    windowKind;
  625.     TWindow    *wobj;
  626.     
  627.     if (aWindow)
  628.         {
  629.         windowKind = ((WindowPeek) aWindow)->windowKind;
  630.         if (windowKind < 0)
  631.             {
  632.             CloseDeskAcc(((WindowPeek)aWindow)->windowKind);
  633.             }
  634.         else if ( ((wobj = GetWindowObject(aWindow)) != nil) &&
  635.                     wobj->CanClose() &&
  636.                     wobj->Close() &&
  637.                     wobj->DeleteAfterClose())
  638.             {
  639.             delete wobj;
  640.             }
  641.         }
  642.     }
  643.